package com.aliang.shopping.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.aliang.shopping.common.PageResult;
import com.aliang.shopping.common.Result;
import com.aliang.shopping.common.ResultCodeEnum;
import com.aliang.shopping.config.OssConfig;
import com.aliang.shopping.contact.BasicConstant;
import com.aliang.shopping.contact.ResultMsgContact;
import com.aliang.shopping.contact.SqlColumnConstant;
import com.aliang.shopping.exception.DataException;
import com.aliang.shopping.log.annotation.OperateLog;
import com.aliang.shopping.log.enums.OperateType;
import com.aliang.shopping.model.converter.NoticeConverter;
import com.aliang.shopping.model.dto.common.PageDTO;
import com.aliang.shopping.model.dto.common.UpdateStatusDTO;
import com.aliang.shopping.model.dto.notice.NoticeImportDTO;
import com.aliang.shopping.model.dto.notice.NoticeInsertDTO;
import com.aliang.shopping.model.dto.notice.NoticeUpdateDTO;
import com.aliang.shopping.model.enums.UserTypeEnum;
import com.aliang.shopping.model.po.Notice;
import com.aliang.shopping.model.vo.notice.NoticeExportVO;
import com.aliang.shopping.model.vo.notice.NoticeVO;
import com.aliang.shopping.security.PreventRepeatSubmit;
import com.aliang.shopping.security.auth.Payload;
import com.aliang.shopping.security.auth.UserHolder;
import com.aliang.shopping.service.NoticeService;
import com.aliang.shopping.util.excel.ExcelUtils;
import com.aliang.shopping.util.excel.listener.NoticeImportListener;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.List;

@RestController
@RequestMapping("/notice")
@AllArgsConstructor
public class NoticeController {

    private final NoticeService noticeService;
    private final NoticeConverter noticeConverter;
    private final ExcelUtils excelUtils;
    private final OssConfig ossConfig;


    /**
     * 公告插入
     *
     * @param insertDTO
     * @return
     */
    @PostMapping("/insert")
    @ApiOperation("公告插入")
    @PreventRepeatSubmit
    @OperateLog(title = "公告插入", type = OperateType.INSERT)
    public Result<String> insertNotice(@RequestBody NoticeInsertDTO insertDTO) {
        //必要字段校验
        if (BeanUtil.hasNullField(insertDTO) || StrUtil.hasBlank(insertDTO.getTitle(), insertDTO.getContent())) {
            throw new DataException(ResultCodeEnum.DATA_LACK);
        }
        // 转换图片数据
        insertDTO.setContent(StrUtil.replace(insertDTO.getContent(), ossConfig.getUrl(), BasicConstant.REPLACE_IMAGE));
        //转换数据
        Notice notice = this.noticeConverter.toPoByInsertDTO(insertDTO);
        Payload payload = UserHolder.get();
        //设置创建人Id及发送端
        notice.setUserId(payload.getId());
        notice.setFormNum(payload.getRole() >= UserTypeEnum.ADMIN.getCode() ? 0 : 1);
        this.noticeService.save(notice);
        return Result.ok(ResultMsgContact.INSERT_SUCCESS);
    }

    /**
     * 公告删除
     *
     * @param ids
     * @return
     */
    @DeleteMapping("/del")
    @ApiOperation("公告删除")
    @PreventRepeatSubmit
    @OperateLog(title = "公告删除", type = OperateType.DELETE)
    public Result<String> delNotice(@RequestBody List<Long> ids) {
        this.noticeService.removeByIds(ids);
        return Result.ok(ResultMsgContact.DELETE_SUCCESS);
    }

    /**
     * 公告更改
     *
     * @param updateDTO
     * @return
     */
    @PutMapping("/update")
    @ApiOperation("公告更改")
    @PreventRepeatSubmit
    @OperateLog(title = "公告更改", type = OperateType.UPDATE)
    public Result<String> updateNotice(@RequestBody NoticeUpdateDTO updateDTO) {
        //必要字段校验
        if (BeanUtil.hasNullField(updateDTO) || StrUtil.hasBlank(updateDTO.getTitle(), updateDTO.getContent())) {
            throw new DataException(ResultCodeEnum.DATA_LACK);
        }
        // 转换图片数据
        updateDTO.setContent(StrUtil.replace(updateDTO.getContent(), ossConfig.getUrl(), BasicConstant.REPLACE_IMAGE));
        //转换数据
        Notice notice = this.noticeConverter.toPoByUpdateDTO(updateDTO);
        this.noticeService.updateById(notice);
        return Result.ok(ResultMsgContact.UPDATE_SUCCESS);
    }

    /**
     * 公告状态更改
     *
     * @param updateDTO
     * @return
     */
    @PutMapping("/update_static")
    @ApiOperation("公告状态更改")
    @PreventRepeatSubmit
    @OperateLog(title = "公告状态更改", type = OperateType.UPDATE_STATUS)
    public Result<String> updateNoticeStatic(@RequestBody UpdateStatusDTO updateDTO) {
        //必要字段校验
        if (BeanUtil.isEmpty(updateDTO)) {
            throw new DataException(ResultCodeEnum.DATA_LACK);
        }
        //转换数据
        Notice notice = this.noticeConverter.toPoByUpdateStaticDTO(updateDTO);
        this.noticeService.updateById(notice);
        return Result.ok(ResultMsgContact.UPDATE_SUCCESS);
    }

    /**
     * 公告分页搜索
     */
    @GetMapping("/getPage")
    @ApiOperation("公告分页搜索")
    public Result<PageResult<NoticeVO>> queryNoticePage(PageDTO pageDTO) {
        //必要字段校验
        if (ObjectUtil.hasNull(pageDTO.getPageSize(), pageDTO.getPageNum())) {
            throw new DataException(ResultCodeEnum.DATA_LACK);
        }
        //查询数据
        PageResult<NoticeVO> result = this.noticeService.selectPage(pageDTO);
        return Result.ok(result);
    }

    /**
     * 公告导入模版下载
     *
     * @param response
     * @throws IOException
     */
    @ApiOperation("公告导入模版下载")
    @GetMapping("/template")
    @PreventRepeatSubmit
    @OperateLog(title = "公告导入模版下载", type = OperateType.DOWNLOAD)
    public void downloadNoticeTemplate(HttpServletResponse response) throws IOException {
        String fileName = "公告导入模版.xlsx";
        this.excelUtils.downloadTemplate(response, fileName);
    }

    /**
     * 公告导入
     */
    @PostMapping("/import")
    @ApiOperation("公告导入")
    @PreventRepeatSubmit
    @OperateLog(title = "公告导入", type = OperateType.IMPORT)
    public Result<String> importNotice(MultipartFile file) throws IOException {
        if (ObjectUtil.isEmpty(file)) {
            throw new DataException(ResultCodeEnum.DATA_LACK);
        }
        //创建数据导入监听器
        NoticeImportListener noticeImportListener = new NoticeImportListener(noticeConverter, noticeService);
        String msg = this.excelUtils.importExcel(file.getInputStream(), NoticeImportDTO.class, noticeImportListener);
        return Result.ok(msg);
    }

    /**
     * 公告导出
     */
    @ApiOperation("导出公告信息")
    @GetMapping("/export")
    @PreventRepeatSubmit
    @OperateLog(title = "导出公告信息", type = OperateType.EXPORT)
    public void exportNotice(PageDTO pageDTO, HttpServletResponse response) throws IOException {
        String fileName = "公告列表.xlsx";
        // 设置请求头
        this.excelUtils.setHeader(response, fileName);
        List<NoticeExportVO> exportUserList = this.noticeService.getExportList(pageDTO);
        //查询数据
        EasyExcel.write(response.getOutputStream(), NoticeExportVO.class).sheet("公告列表")
                .doWrite(exportUserList);
    }


    @ApiOperation("获取面向用户的公告列表前4条")
    @GetMapping("/getTop4NoticeWithUser")
    public Result<List<NoticeVO>> getTop4NoticeWithUser() {
        List<Notice> list = this.noticeService.list(
                new LambdaQueryWrapper<Notice>()
                        .eq(Notice::getStatus, SqlColumnConstant.STATUS_OK)
                        .eq(Notice::getToNum, SqlColumnConstant.NOTICE_TO_USER) //给用户的
                        .orderByAsc(Notice::getCreateTime)
                        .last("limit 4")
        );
        if (list.isEmpty()) {
            return Result.ok(Collections.emptyList());
        }
        // 转换数据
        return Result.ok(this.noticeConverter.toVOList(list));
    }

    @ApiOperation("获取全部面向用户的公告列表")
    @GetMapping("/getAllNoticeWithUser")
    public Result<List<NoticeVO>> getAllNoticeWithUser() {
        List<Notice> list = this.noticeService.list(
                new LambdaQueryWrapper<Notice>()
                        .eq(Notice::getStatus, SqlColumnConstant.STATUS_OK)
                        .eq(Notice::getToNum, SqlColumnConstant.NOTICE_TO_USER) //给用户的
                        .orderByAsc(Notice::getCreateTime)
        );
        if (list.isEmpty()) {
            return Result.ok(Collections.emptyList());
        }
        // 转换数据
        return Result.ok(this.noticeConverter.toVOList(list));
    }
}
